import { formattedTime, unixDateConverter } from "./timeConverter"
import isEqual from "lodash/isEqual"

export type AppointmentBodyState = {
  allSelectedClients?: any
  startTime?: string
  appointmentDate?: string
  endTime?: string
  select_dates?: boolean
  clients?: []
  selected_dates?: []
  weekly_repeat?: boolean
  number_of_weeks?: string
  weeklyRepeatGap?: string
  appointmentLocationId?: string
  appointment_services?: [
    {
      id: string
      services: [
        {
          service: string
          fees: string
        },
      ]
    },
  ]
}

export function generateBodyWithBooking(appointmentState: any, id: string) {
  const start_date = unixDateConverter(appointmentState?.appointmentDate)
  let selected_dates =
    appointmentState?.selectedDatesArray.map((item) => {
      return Math.floor(new Date(item).getTime() / 1000)
    }) ?? []
  const isStartDatePresent = selected_dates.includes(start_date)
  if (!isStartDatePresent && appointmentState.selectedDates?.length) {
    // If start_date is not present, push it into the array
    selected_dates.push(start_date)
  }

  return {
    id: id,
    body: {
      start_time: formattedTime(appointmentState?.startTime),
      start_date,
      end_time: formattedTime(appointmentState?.endTime),
      select_dates: appointmentState?.selectedDates?.length ? true : false,
      clients: appointmentState?.allSelectedClients.map((element) => {
        return element?.id
      }),
      selected_dates: appointmentState?.selectedDatesArray?.map((item) => {
        return Math.floor(new Date(item).getTime() / 1000)
      }),
      weekly_repeat: false,
      number_of_weeks: 1,
      weekly_repeat_gap: 1,
      provider_location: "",
      appointment_services: appointmentState?.allSelectedClients.map((element) => {
        return {
          id: element?.id,
          services: element?.services?.map((item) => {
            return {
              service: item?.id,
              fees: item?.fee,
            }
          }),
        }
      }),
      google: appointmentState?.meetCheckBox ? true : false,
      zoom: appointmentState?.zoomCheckBox ? true : false,
      telehealth: appointmentState?.healthCheckBox ? true : false,
      status: 1,
    },
  }
}

export function generateBookingBody(appointmentState: any) {
  const start_date = unixDateConverter(appointmentState?.appointmentDate)
  let selected_dates =
    appointmentState?.selectedDatesArray?.map((item) => {
      return Math.floor(new Date(item).getTime() / 1000)
    }) ?? []
  const isStartDatePresent = selected_dates.includes(start_date)
  if (!isStartDatePresent && appointmentState?.selectedDatesArray?.length) {
    // If start_date is not present, push it into the array
    selected_dates.push(start_date)
  }

  return {
    start_time: formattedTime(appointmentState?.bookingStartTime),
    start_date,
    end_time: formattedTime(appointmentState?.bookingEndTime),
    select_dates: appointmentState?.selectedDatesArray?.length ? true : false,
    room: appointmentState?.roomId,
    selected_dates,
  }
}

//TODO flat selected dates array here in selected_dates[]
export function generateGetRoomsBody(appointmentState: any, providerState: any) {
  return {
    body: {
      start_time: appointmentState?.bookingStartTime
        ? formattedTime(appointmentState?.bookingStartTime)
        : "09:00",
      end_time: appointmentState?.bookingEndTime
        ? formattedTime(appointmentState?.bookingEndTime)
        : "10:00",
      //TODO selected dates functionality
      selected_dates: appointmentState?.selectedDatesArray?.length
        ? appointmentState?.selectedDatesArray.map((item) => {
            return Math.floor(new Date(item).getTime() / 1000)
          })
        : [`${unixDateConverter(appointmentState?.appointmentDate)}`],
      provider: providerState?.provider?.id,
    },
    locationId: appointmentState?.appointmentLocationId,
  }
}

export function generateBodyWithOutBooking(appointmentState: any) {
  const start_date = unixDateConverter(appointmentState?.appointmentDate)
  let selected_dates =
    appointmentState?.selectedDatesArray?.map((item) => {
      return Math.floor(new Date(item).getTime() / 1000)
    }) ?? []

  const isStartDatePresent = selected_dates.includes(start_date)
  if (!isStartDatePresent && appointmentState?.selectedDatesArray?.length) {
    // If start_date is not present, push it into the array
    selected_dates.push(start_date)
  }

  return {
    start_time: formattedTime(appointmentState?.startTime),
    start_date,
    end_time: formattedTime(appointmentState?.endTime),
    select_dates: appointmentState?.selectedDatesArray?.length ? true : false,
    clients: appointmentState?.allSelectedClients.map((element) => {
      return element?.id
    }),
    selected_dates,
    weekly_repeat: appointmentState?.number_of_weeks ? true : false,
    number_of_weeks: appointmentState?.number_of_weeks ? appointmentState?.number_of_weeks : 0,
    weekly_repeat_gap: appointmentState?.weeklyRepeatGap ? appointmentState?.weeklyRepeatGap : 0,
    provider_location: appointmentState?.appointmentLocationId,
    appointment_services: appointmentState?.allSelectedClients.map((element) => {
      return {
        id: element?.id,
        services: element?.services?.map((item) => {
          return {
            service: item?.id,
            fees: item?.fee,
          }
        }),
      }
    }),
    google: appointmentState?.meetCheckBox ? true : false,
    zoom: appointmentState?.zoomCheckBox ? true : false,
    telehealth: appointmentState?.healthCheckBox ? true : false,
    status: 1,
  }
}

export function generateRoomCostBody(appointmentState: any) {
  return {
    location: appointmentState?.appointmentLocationId,
    room: appointmentState?.roomId,
  }
}

// This function is designed to determine and return values that have been altered
// when compared to the saved object in the appointmentDetails state.
export function generateUpdatedBodyWithOutBooking(appointmentState: any) {
  let start_time = formattedTime(appointmentState?.startTime)
  let start_date = unixDateConverter(appointmentState?.appointmentDate)
  let end_time = formattedTime(appointmentState?.endTime)
  let select_dates = appointmentState?.selectedDatesArray?.length ? true : false

  //existing_clients
  let existing_clients = appointmentState?.appointmentDetails?.appointment_services?.map(
    (element) => {
      return element?.id?.id
    },
  )
  //altered clients
  let clients = appointmentState?.allSelectedClients.map((element) => {
    return element?.id
  })

  const clientsComparison = isEqual(clients, existing_clients)

  //Altered selected_dates Array
  let selected_dates =
    appointmentState?.selectedDatesArray?.map((item) =>
      Math.floor(new Date(item).getTime() / 1000),
    ) ?? []
  const isStartDatePresent = selected_dates.includes(start_date) || false
  if (!isStartDatePresent && appointmentState?.selectedDatesArray?.length) {
    // If start_date is not present, push it into the array
    selected_dates.push(start_date)
  }

  const selectedDatesComparison = isEqual(
    selected_dates,
    appointmentState?.appointmentDetails?.selected_dates,
  )

  let weekly_repeat = appointmentState?.number_of_weeks ? true : false
  let number_of_weeks = appointmentState?.number_of_weeks ? appointmentState?.number_of_weeks : 0
  let weekly_repeat_gap = appointmentState?.weeklyRepeatGap ? appointmentState?.weeklyRepeatGap : 0
  //altered provider_location
  let provider_location = appointmentState?.appointmentLocationId
  let providerLocationComparison =
    provider_location === appointmentState?.appointmentDetails?.provider_location?.id

  //altered appointment_services
  let updated_appointment_services = appointmentState?.allSelectedClients.map((element) => {
    return {
      id: element?.id,
      services: element?.services?.map((item) => {
        return {
          service: item?.id,
          fees: item?.fee,
        }
      }),
    }
  })
  //backend fetched appointment_services to compare
  let appointment_services = appointmentState?.appointmentDetails?.appointment_services.map(
    (element: any) => {
      return {
        id: element?.id?.id,
        services: element?.services?.map((item) => {
          return {
            service: item?.service?.id,
            fees: item?.service?.fee,
          }
        }),
      }
    },
  )

  const appointmentServicesComparison = isEqual(appointment_services, updated_appointment_services)

  let google = appointmentState?.meetCheckBox ? true : false
  let zoom = appointmentState?.zoomCheckBox ? true : false
  let telehealth = appointmentState?.healthCheckBox ? true : false

  return {
    ...(start_time !== appointmentState?.appointmentDetails?.start_time && {
      start_time,
    }),
    ...(start_date !== parseInt(appointmentState?.appointmentDetails?.start_date) && {
      start_date,
    }),
    ...(end_time !== appointmentState?.appointmentDetails?.end_time && {
      end_time,
    }),
    ...(select_dates !== appointmentState?.appointmentDetails?.select_dates && {
      select_dates,
    }),
    ...(!clientsComparison && {
      clients,
    }),
    ...(!selectedDatesComparison && {
      selected_dates,
    }),
    ...(weekly_repeat !== appointmentState?.appointmentDetails?.weekly_repeat && {
      weekly_repeat,
    }),
    ...(number_of_weeks !== appointmentState?.appointmentDetails?.number_of_weeks && {
      number_of_weeks,
    }),
    ...(weekly_repeat_gap !== appointmentState?.appointmentDetails?.weekly_repeat_gap && {
      weekly_repeat_gap,
    }),
    ...(providerLocationComparison == false && {
      provider_location,
    }),
    ...(!appointmentServicesComparison && {
      appointment_services: updated_appointment_services,
    }),
    ...(telehealth !== appointmentState?.appointmentDetails?.telehealth && {
      telehealth,
    }),
    ...(google !== appointmentState?.appointmentDetails?.google && {
      google,
    }),
    ...(zoom !== appointmentState?.appointmentDetails?.zoom && {
      zoom,
    }),
    status: 1,
  }
}

export function updateBookingBody(appointmentState: any) {
  const start_time = formattedTime(appointmentState?.bookingStartTime)
  const start_date = unixDateConverter(appointmentState?.appointmentDate)
  const end_time = formattedTime(appointmentState?.bookingEndTime)
  const select_dates = appointmentState?.selectedDatesArray?.length ? true : false
  const room = appointmentState?.roomId
  const selected_dates =
    appointmentState?.selectedDatesArray?.map((item) => {
      return Math.floor(new Date(item).getTime() / 1000)
    }) ?? []

  const isStartDatePresent = selected_dates.includes(start_date)
  if (!isStartDatePresent && appointmentState?.selectedDates?.length) {
    // If start_date is not present, push it into the array
    selected_dates.push(start_date)
  }

  const selectedDatesComparison = isEqual(
    selected_dates,
    appointmentState?.appointmentDetails?.booking?.selected_dates,
  )
  return {
    ...(start_time !== appointmentState?.appointmentDetails?.booking?.start_time && {
      start_time,
    }),
    ...(end_time !== appointmentState?.appointmentDetails?.booking?.end_time && {
      end_time,
    }),
    ...(start_date !== parseInt(appointmentState?.appointmentDetails?.booking?.start_date) && {
      start_date,
    }),
    ...(select_dates !== appointmentState?.appointmentDetails?.booking?.select_dates && {
      select_dates,
    }),
    ...(!selectedDatesComparison && {
      selected_dates,
    }),
    ...(select_dates !== appointmentState?.appointmentDetails?.booking?.select_dates && {
      select_dates,
    }),
    ...(room !== appointmentState?.appointmentDetails?.booking?.room?.id && {
      room,
    }),
  }
}

export function generateUpdatedBodyWithBooking(appointmentState: any) {
  const start_date = unixDateConverter(appointmentState?.appointmentDate)
  let selected_dates =
    appointmentState?.selectedDatesArray?.map((item) => {
      return Math.floor(new Date(item).getTime() / 1000)
    }) ?? []
  const isStartDatePresent = selected_dates.includes(start_date)
  if (!isStartDatePresent && appointmentState?.selectedDates?.length) {
    // If start_date is not present, push it into the array
    selected_dates.push(start_date)
  }
  const selectedDatesComparison = isEqual(
    selected_dates,
    appointmentState?.appointmentDetails?.selected_dates,
  )
  const start_time = formattedTime(appointmentState?.startTime)
  const end_time = formattedTime(appointmentState?.endTime)
  const select_dates = appointmentState?.selectedDates?.length ? true : false

  //existing_clients
  let existing_clients = appointmentState?.appointmentDetails?.appointment_services?.map(
    (element) => {
      return element?.id?.id
    },
  )
  //altered clients
  let clients = appointmentState?.allSelectedClients.map((element) => {
    return element?.id
  })

  const clientsComparison = isEqual(clients, existing_clients)

  //altered appointment_services
  let updated_appointment_services = appointmentState?.allSelectedClients.map((element) => {
    return {
      id: element?.id,
      services: element?.services?.map((item) => {
        return {
          service: item?.id,
          fees: item?.fee,
        }
      }),
    }
  })
  //backend fetched appointment_services to compare
  let appointment_services = appointmentState?.appointmentDetails?.appointment_services.map(
    (element: any) => {
      return {
        id: element?.id?.id,
        services: element?.services?.map((item) => {
          return {
            service: item?.service?.id,
            fees: item?.service?.fee,
          }
        }),
      }
    },
  )

  const appointmentServicesComparison = isEqual(appointment_services, updated_appointment_services)
  const google = appointmentState?.meetCheckBox ? true : false
  const zoom = appointmentState?.zoomCheckBox ? true : false
  const telehealth = appointmentState?.healthCheckBox ? true : false

  return {
    ...(start_time !== appointmentState?.appointmentDetails?.start_time && {
      start_time,
    }),
    ...(end_time !== appointmentState?.appointmentDetails?.end_time && {
      end_time,
    }),
    ...(start_date !== parseInt(appointmentState?.appointmentDetails?.start_date) && {
      start_date,
    }),
    ...(select_dates !== appointmentState?.appointmentDetails?.select_dates && {
      select_dates,
    }),
    ...(!selectedDatesComparison && {
      selected_dates,
    }),
    ...(!clientsComparison && {
      clients,
    }),
    weekly_repeat: false,
    number_of_weeks: 0,
    weekly_repeat_gap: 0,
    provider_location: "",
    ...(!appointmentServicesComparison && {
      appointment_services: updated_appointment_services,
    }),
    ...(telehealth !== appointmentState?.appointmentDetails?.telehealth && {
      telehealth,
    }),
    ...(google !== appointmentState?.appointmentDetails?.google && {
      google,
    }),
    ...(zoom !== appointmentState?.appointmentDetails?.zoom && {
      zoom,
    }),
    status: 1,
  }
}
